import * as fs from 'fs';
import * as path from 'path';
import { PaymentChannel } from '@prisma/client';
import { ChannelWeightConfig, ChannelConfig, ChannelSelectionResult, ChannelTestResult } from '../types/channelConfig';
import { Logger } from '../utils/logger';

const CONFIG_FILE_PATH = path.join(__dirname, '../config/channelWeights.json');

export class ChannelConfigService {
  private config: ChannelWeightConfig | null = null;
  private lastLoadTime: number = 0;
  private readonly CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存

  /**
   * 加载渠道权重配置
   */
  private loadConfig(): ChannelWeightConfig {
    const now = Date.now();
    
    // 如果配置已缓存且未过期，直接返回
    if (this.config && (now - this.lastLoadTime) < this.CACHE_DURATION) {
      return this.config;
    }

    try {
      const configData = fs.readFileSync(CONFIG_FILE_PATH, 'utf-8');
      this.config = JSON.parse(configData) as ChannelWeightConfig;
      this.lastLoadTime = now;
      
      Logger.info('渠道权重配置加载成功', {
        version: this.config.version,
        lastUpdated: this.config.lastUpdated,
        channelCount: Object.keys(this.config.channels).length
      });
      
      return this.config;
    } catch (error) {
      Logger.error('加载渠道权重配置失败', error);
      
      // 返回默认配置
      return this.getDefaultConfig();
    }
  }

  /**
   * 保存渠道权重配置
   */
  async saveConfig(config: ChannelWeightConfig): Promise<void> {
    try {
      // 更新时间戳
      config.lastUpdated = new Date().toISOString();
      
      // 确保目录存在
      const configDir = path.dirname(CONFIG_FILE_PATH);
      if (!fs.existsSync(configDir)) {
        fs.mkdirSync(configDir, { recursive: true });
      }
      
      // 写入文件
      fs.writeFileSync(CONFIG_FILE_PATH, JSON.stringify(config, null, 2), 'utf-8');
      
      // 更新内存缓存
      this.config = config;
      this.lastLoadTime = Date.now();
      
      Logger.info('渠道权重配置保存成功', {
        version: config.version,
        lastUpdated: config.lastUpdated
      });
    } catch (error) {
      Logger.error('保存渠道权重配置失败', error);
      throw new Error('保存配置文件失败');
    }
  }

  /**
   * 获取默认配置
   */
  private getDefaultConfig(): ChannelWeightConfig {
    return {
      version: "1.0.0",
      lastUpdated: new Date().toISOString(),
      defaultConfig: {
        algorithm: "weighted_random",
        fallbackStrategy: "round_robin"
      },
      channels: {
        [PaymentChannel.TOPPAY]: {
          channelId: "10001",
          channelName: "xxxpay",
          displayName: "TopPay",
          weight: 5000,
          isEnabled: true,
          minAmount: 100,
          maxAmount: 50000,
          dailyLimit: 1000000,
          priority: 1
        },
        [PaymentChannel.PAY668]: {
          channelId: "10002",
          channelName: "xxxpay",
          displayName: "668Pay",
          weight: 2000,
          isEnabled: true,
          minAmount: 500,
          maxAmount: 20000,
          dailyLimit: 500000,
          priority: 2
        },
        [PaymentChannel.LSPPAY]: {
          channelId: "10003",
          channelName: "xxxpay",
          displayName: "LSPPAY",
          weight: 2000,
          isEnabled: false,
          minAmount: 100,
          maxAmount: 30000,
          dailyLimit: 800000,
          priority: 3
        },
        [PaymentChannel.HUIFENG]: {
          channelId: "10004",
          channelName: "huifengpay",
          displayName: "汇沣支付",
          weight: 1000,
          isEnabled: false,
          minAmount: 100,
          maxAmount: 50000,
          dailyLimit: 500000,
          priority: 4
        },
        [PaymentChannel.NASKI]: {
          channelId: "10005",
          channelName: "naskipay",
          displayName: "NASKI支付",
          weight: 1500,
          isEnabled: false,
          minAmount: 100,
          maxAmount: 50000,
          dailyLimit: 600000,
          priority: 5
        }
      }
    };
  }

  /**
   * 获取所有渠道配置
   */
  getChannelConfigs(): ChannelWeightConfig {
    return this.loadConfig();
  }

  /**
   * 获取单个渠道配置
   */
  getChannelConfig(channel: PaymentChannel): ChannelConfig | null {
    const config = this.loadConfig();
    return config.channels[channel] || null;
  }

  /**
   * 更新单个渠道配置
   */
  async updateChannelConfig(channel: PaymentChannel, channelConfig: Partial<ChannelConfig>): Promise<void> {
    const config = this.loadConfig();
    
    if (!config.channels[channel]) {
      throw new Error(`渠道 ${channel} 不存在`);
    }

    // 合并配置
    config.channels[channel] = {
      ...config.channels[channel],
      ...channelConfig
    };

    await this.saveConfig(config);
  }

  /**
   * 批量更新渠道权重
   */
  async batchUpdateWeights(weights: Record<PaymentChannel, number>): Promise<void> {
    const config = this.loadConfig();

    for (const [channel, weight] of Object.entries(weights)) {
      if (config.channels[channel as PaymentChannel]) {
        config.channels[channel as PaymentChannel].weight = weight;
      }
    }

    await this.saveConfig(config);
  }

  /**
   * 根据金额和权重选择最优渠道
   */
  selectOptimalChannel(amount: number, availableChannels: PaymentChannel[]): ChannelSelectionResult {
    const config = this.loadConfig();
    
    // 筛选满足条件的渠道
    const eligibleChannels = availableChannels.filter(channel => {
      const channelConfig = config.channels[channel];
      if (!channelConfig) return false;
      
      return channelConfig.isEnabled &&
             amount >= channelConfig.minAmount &&
             amount <= channelConfig.maxAmount;
    });

    if (eligibleChannels.length === 0) {
      return {
        selectedChannel: null,
        reason: '没有满足金额范围且已启用的渠道',
        availableChannels,
        totalWeight: 0
      };
    }

    // 如果只有一个可用渠道，直接返回
    if (eligibleChannels.length === 1) {
      return {
        selectedChannel: eligibleChannels[0],
        reason: '只有一个满足条件的渠道',
        availableChannels: eligibleChannels,
        totalWeight: config.channels[eligibleChannels[0]].weight
      };
    }

    // 计算总权重
    const totalWeight = eligibleChannels.reduce((sum, channel) => {
      return sum + config.channels[channel].weight;
    }, 0);

    if (totalWeight === 0) {
      // 如果所有渠道权重都为0，使用轮询策略
      const selectedChannel = eligibleChannels[Math.floor(Math.random() * eligibleChannels.length)];
      return {
        selectedChannel,
        reason: '所有渠道权重为0，使用随机选择',
        availableChannels: eligibleChannels,
        totalWeight: 0
      };
    }

    // 加权随机选择
    const randomWeight = Math.random() * totalWeight;
    let currentWeight = 0;
    
    for (const channel of eligibleChannels) {
      currentWeight += config.channels[channel].weight;
      if (randomWeight <= currentWeight) {
        return {
          selectedChannel: channel,
          reason: `基于权重的随机选择 (权重: ${config.channels[channel].weight}/${totalWeight})`,
          availableChannels: eligibleChannels,
          totalWeight,
          selectionWeight: config.channels[channel].weight
        };
      }
    }

    // 兜底：返回最后一个渠道
    const fallbackChannel = eligibleChannels[eligibleChannels.length - 1];
    return {
      selectedChannel: fallbackChannel,
      reason: '权重计算异常，使用兜底渠道',
      availableChannels: eligibleChannels,
      totalWeight,
      selectionWeight: config.channels[fallbackChannel].weight
    };
  }

  /**
   * 测试渠道选择算法
   */
  testChannelSelection(amount: number, testCount: number, availableChannels: PaymentChannel[]): ChannelTestResult {
    const startTime = Date.now();
    const results: Record<PaymentChannel, number> = {
      [PaymentChannel.TOPPAY]: 0,
      [PaymentChannel.PAY668]: 0,
      [PaymentChannel.LSPPAY]: 0,
      [PaymentChannel.HUIFENG]: 0,
      [PaymentChannel.NASKI]: 0
    };

    // 执行测试
    for (let i = 0; i < testCount; i++) {
      const selection = this.selectOptimalChannel(amount, availableChannels);
      if (selection.selectedChannel) {
        results[selection.selectedChannel]++;
      }
    }

    // 计算百分比
    const percentages: Record<PaymentChannel, number> = {
      [PaymentChannel.TOPPAY]: (results[PaymentChannel.TOPPAY] / testCount) * 100,
      [PaymentChannel.PAY668]: (results[PaymentChannel.PAY668] / testCount) * 100,
      [PaymentChannel.LSPPAY]: (results[PaymentChannel.LSPPAY] / testCount) * 100,
      [PaymentChannel.HUIFENG]: (results[PaymentChannel.HUIFENG] / testCount) * 100,
      [PaymentChannel.NASKI]: (results[PaymentChannel.NASKI] / testCount) * 100
    };

    // 获取总权重
    const config = this.loadConfig();
    const eligibleChannels = availableChannels.filter(channel => {
      const channelConfig = config.channels[channel];
      return channelConfig?.isEnabled &&
             amount >= channelConfig.minAmount &&
             amount <= channelConfig.maxAmount;
    });
    
    const totalWeight = eligibleChannels.reduce((sum, channel) => {
      return sum + config.channels[channel].weight;
    }, 0);

    return {
      testCount,
      amount,
      results,
      percentages,
      totalWeight,
      duration: Date.now() - startTime
    };
  }

  /**
   * 重置为默认配置
   */
  async resetToDefault(): Promise<void> {
    const defaultConfig = this.getDefaultConfig();
    await this.saveConfig(defaultConfig);
  }

  /**
   * 强制重新加载配置
   */
  reloadConfig(): ChannelWeightConfig {
    this.config = null;
    this.lastLoadTime = 0;
    return this.loadConfig();
  }
}

// 创建服务实例
export const channelConfigService = new ChannelConfigService();